#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include "Comm.hpp"
#include <cstring>
#include <unistd.h>

const static int disconnect_and_reconnect = 5;

void Usage(const char *proc)
{
    std::cout << "Usage:\n\t" << proc << " server_ip server_port" << std::endl;
}

bool vistServer(std::string server_ip, uint16_t server_port, int &cnt)
{
    // 1.socket
    int Socket = socket(AF_INET, SOCK_STREAM, 0);
    if (Socket < 0)
    {
        std::cout << "socket failure" << std::endl;
        return false;
    }
    std::string message;
    int w;
    bool ret = true;

    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(server_port);
    inet_pton(AF_INET, server_ip.c_str(), &server.sin_addr);

    int n = connect(Socket, CONV(&server), sizeof(server));
    if (n != 0)
    {
        std::cout << "connect faulure" << std::endl;
        ret = false;
        goto END;
    }
    std::cout << "connect success" << std::endl;
    cnt = 1;

    char buffer[1024];
    n = read(Socket, buffer, sizeof(buffer));
    std::cout << "服务列表：" << std::endl;
    if (n > 0)
    {
        buffer[n] = 0;
        std::cout << buffer << std::endl;
    }

    std::cout << "请输入服务选项#:";
    getline(std::cin, message);
    w = write(Socket, message.c_str(), message.size());

    std::cout << "client Enter#:";
    getline(std::cin, message);
    if (message == "quit")
        goto END;
    w = write(Socket, message.c_str(), message.size());
    if (w > 0)
    {
        char buffer[1024];
        int r = read(Socket, buffer, sizeof(buffer));
        if (r > 0)
        {
            buffer[r] = 0;
            std::cout << "server->" << buffer << std::endl;
        }
        else if (r == 0)
        {
            goto END;
        }
        else
        {
            std::cout << "read failure" << std::endl;
            ret = false;
            goto END;
        }
    }
    else
    {
        std::cout << "write failure" << std::endl;
        ret = false;
        goto END;
    }
END:
    close(Socket);
    return ret;
}

int main(int argc, char *argv[])
{
    std::string server_ip = argv[1];
    uint16_t server_port = std::stoi(argv[2]);
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(Usage_Err);
    }
    int cnt = 1;
    while (cnt <= disconnect_and_reconnect)
    {
        bool result = vistServer(server_ip, server_port, cnt);
        if (result)
        {
            break;
        }
        else
        {
            sleep(1);
            std::cout << "server offline, retrying..., count : " << cnt << std::endl;
            cnt++;
        }
    }
    if (cnt >= disconnect_and_reconnect)
    {
    std:
        std::cout << "server offline" << std::endl;
    }

    return 0;
}

// 修改一：断线重连版本：
//  const static int disconnect_and_reconnect = 5;

// void Usage(const char *proc)
// {
//     std::cout << "Usage:\n\t" << proc << " server_ip server_port" << std::endl;
// }

// bool vistServer(std::string server_ip, uint16_t server_port, int &cnt)
// {
//     // 1.socket
//     int Socket = socket(AF_INET, SOCK_STREAM, 0);
//     if (Socket < 0)
//     {
//         std::cout << "socket failure" << std::endl;
//         return false;
//     }

//     bool ret = true;
//     struct sockaddr_in server;
//     memset(&server, 0, sizeof(server));
//     server.sin_family = AF_INET;
//     server.sin_port = htons(server_port);
//     inet_pton(AF_INET, server_ip.c_str(), &server.sin_addr);

//     int n = connect(Socket, CONV(&server), sizeof(server));
//     if (n != 0)
//     {
//         std::cout << "connect faulure" << std::endl;
//         ret = false;
//         goto END;
//     }
//     std::cout << "connect success" << std::endl;
//     cnt = 1;
//     while (true)
//     {
//         std::string message;
//         std::cout << "client Enter#:";
//         getline(std::cin, message);
//         if(message == "quit")
//             goto END;
//         int n = write(Socket, message.c_str(), message.size());
//         if (n > 0)
//         {
//             char buffer[1024];
//             int r = read(Socket, buffer, sizeof(buffer));
//             if (r > 0)
//             {
//                 buffer[r] = 0;
//                 std::cout << "server->" << buffer << std::endl;
//             }
//             else if (r == 0)
//             {
//                 goto END;
//             }
//             else
//             {
//                 std::cout << "read failure" << std::endl;
//                 ret = false;
//                 goto END;
//             }
//         }
//         else
//         {
//             std::cout << "write failure" << std::endl;
//             ret = false;
//             goto END;
//         }
//     }
// END:
//     close(Socket);
//     return ret;
// }

// int main(int argc, char *argv[])
// {
//     std::string server_ip = argv[1];
//     uint16_t server_port = std::stoi(argv[2]);
//     if (argc != 3)
//     {
//         Usage(argv[0]);
//         exit(Usage_Err);
//     }
//     int cnt = 1;
//     while (cnt <= disconnect_and_reconnect)
//     {
//         bool result = vistServer(server_ip, server_port, cnt);
//         if (result)
//         {
//             break;
//         }
//         else
//         {
//             sleep(1);
//             std::cout << "server offline, retrying..., count : " << cnt << std::endl;
//             cnt++;
//         }
//     }
//     if (cnt >= disconnect_and_reconnect)
//     {
//     std:
//         std::cout << "server offline" << std::endl;
//     }

//     return 0;
// }